import Entity from '../model/Entity';
import Hero from "../view/HeroView";
const { ccclass, property } = cc._decorator;

//人物朝向
enum eDir {
    up = 'up',
    down = 'down',
    left = 'left',
    right = 'right'
}

@ccclass
export default class HeroMove extends cc.Component {

    @property(cc.Texture2D)
    image: cc.Texture2D = null

    @property(cc.TiledMap)
    tiled: cc.TiledMap = null

    hero: Hero = null;

    status: string = '';

    heroLayer: cc.TiledLayer = null;

    moveDir(dir: eDir) {
        let movePos = cc.v3();

        let status = '';
        if (this.node.getNumberOfRunningActions() == 0) {
            switch (dir) {
                case eDir.up:
                    movePos.y = 32;
                    status = 'up'
                    break;
                case eDir.down:
                    movePos.y = -32;
                    status = 'down'
                    break;
                case eDir.left:
                    movePos.x = -32;
                    status = 'left'
                    break;
                case eDir.right:
                    movePos.x = 32;
                    status = 'right'
                    break;
            }
            let pos = this.node.position.add(movePos)
            let tilePos = this.posConventTile(pos);;
            //是否可以移动
            if (!this.isCanMove(tilePos)) {
                return;
            }
            this.moveEvent(tilePos);
            cc.tween(this.node)
                .call(() => {
                    this.playAnimation(status)
                })
                .by(0.2, { position: movePos }).start()
        }
    }

    onKeyDown(e: cc.Event.EventKeyboard) {
        switch (e.keyCode) {
            case cc.macro.KEY.up:
            case cc.macro.KEY.w:
                this.moveDir(eDir.up)
                break
            case cc.macro.KEY.down:
            case cc.macro.KEY.s:
                this.moveDir(eDir.down)
                break
            case cc.macro.KEY.left:
            case cc.macro.KEY.a:
                this.moveDir(eDir.left)
                break
            case cc.macro.KEY.right:
            case cc.macro.KEY.d:
                this.moveDir(eDir.right)
                break
        }
    }

    initAnmation(y: number, dir: string) {
        let frames: Array<cc.SpriteFrame> = [];
        for (let i = 0; i < 4; i++) {
            frames.push(new cc.SpriteFrame(this.image, cc.rect(i * 32, y * 32, 32, 32)))
        }
        let clip = cc.AnimationClip.createWithSpriteFrames(frames, frames.length);
        clip.name = dir;
        clip.wrapMode = cc.WrapMode.Loop;
        let animation = this.getComponent(cc.Animation);
        animation.addClip(clip);
    }
    playAnimation(dir: string) {
        let animation = this.getComponent(cc.Animation)

        if (this.status != dir) {
            animation.play(dir)
            this.status = dir
        }
    }

    onLoad() {
        this.heroLayer = this.tiled.getLayer('hero');
        this.initHero();
        this.initAnmation(0, 'down');
        this.initAnmation(1, 'left');
        this.initAnmation(2, 'right');
        this.initAnmation(3, 'up');

        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);

        this.hero = new Hero();
    }

    start() {

    }

    //update(dt) { }

    posConventTile(v3: cc.Vec3): cc.Vec3 {
        let x = v3.x / this.tiled.getTileSize().width;

        let h = this.tiled.getMapSize().height;
        let ts = this.tiled.getTileSize().height;
        let y = h - (v3.y / ts) - 1;
        return cc.v3(x, y);
    }

    isCanMove(v3: cc.Vec3): boolean {
        let wall: Entity = this.tiled.node.getComponent('wall');
        return wall.isCanMove(v3)
    }

    moveEvent(tild: cc.Vec3) {
        //item
        let item: Entity = this.tiled.node.getComponent('item');
        item.doEvent(tild, this.node);

        //Enemy
        let enemy: Entity = this.tiled.node.getComponent('Enemy');
        enemy.doEvent(tild, this.node);

        //door
        let door: Entity = this.tiled.node.getComponent('door');
        door.doEvent(tild, this.node);
    }

    initHero() {
        let s = this.heroLayer.getLayerSize();
        for (let y = 0; y < s.height; y++) {
            for (let x = 0; x < s.width; x++) {
                let gid = this.heroLayer.getTileGIDAt(cc.v2(x, y))
                if (gid != 0) {
                    let pos = this.heroLayer.getPositionAt(x, y);
                    this.node.position = cc.v3(pos);
                }
            }
        }
    }
}
